/* 
 * File:   SymbolTable.h
 * Author: Kamil Chaber
 */

#ifndef SYMBOLTABLE_H
#define	SYMBOLTABLE_H

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include "symboltablerecord.h"

using namespace std;

class SymbolTable {
private:
    vector<SymbolTableRecord> elements;
    
    /**
     * The first free adress on the main stack
     */
    int currAddress;
    
    /**
     * Initializes the symbol table with the reserved values identifiers, procedures etc...
     */
    void initReservedValues();
public:
    SymbolTable();
    
    /**
     * Inserts the new identifier into the symbol table and returns the index to its.
     * If given identifier already exists, it returns the index to its.
     * @param identifier
     * @return 
     */
    int insertIdentifier(string identifier);
    
    /**
     * Inserts new number to the symbol table no matter if the number already exists.
     * @param number
     * @return 
     */
    int insertNumber(string number);
    
    int insertRecord(SymbolTableRecord& rec);
    
    /**
     * Returns the element of the symbol table located at the given index
     * @param index
     * @return 
     */
    SymbolTableRecord& getElement(int index);
    
    /**
     * Returns the main program element
     * @return 
     */
    SymbolTableRecord& getProgramElement();
    
    int getLastTempVariableIndex();
    
    /**
     * Returns the reference to the symbol table elements
     * @return 
     */
    vector<SymbolTableRecord>& getElements();
    
    /**
     * Allocates new address for the element located at the index'th place in the symbol table
     * and increases appropriately the next available address  
     * @param index
     * @param scope
     * @return address assigned to the element
     */
    string allocateAddress(int index);
    
    /**
     * Sets up the type of the given record.
     * @param varIndex
     * @param type
     */
    void setUpElementType(int varIndex, SymbolTableElementType type);
    
    string toString();

    virtual ~SymbolTable();
private:
    
};

/**
 * Predicate checking if the SymbolTableRecord is the program record
 * @param rec
 * @return 
 */
static bool IsProgramRecord(const SymbolTableRecord& rec) {
    return (rec.type == RECORD_TYPE_PROGRAM);
}

/**
 * Predicate checking if the SymbolTableRecord is the temporary variable record
 * @param rec
 * @return 
 */
static bool IsTemporaryVariable(const SymbolTableRecord& rec) {
    return (rec.type == RECORD_TYPE_TEMP_VARIABLE);
}

#endif	/* SYMBOLTABLE_H */

